package com.budwk.app.thirdLogin.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.thirdLogin.ChinaMobileThirdService;
import com.budwk.app.util.HttpUtils;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

/**
 * @author ZY.Wang
 * @since 2023/7/10
 */
@IocBean
public class ChinaMobileThirdServiceImpl implements ChinaMobileThirdService {

    @Inject
    private PropertiesProxy propertiesProxy;

    public static final String SUCCESS_HTTP_CODE = "103000";
    public static final String encryptionAlgorithm_RSA = "RSA";
    public static final String encryptionAlgorithm_SM = "SM";

    @Override
    public String parseTokenToPhone(String phoneToken) {
        String tokenUrl = "https://onekey2.cmpassport.com/unisdk/rsapi/loginTokenValidate";

        String sign = createSignWithRSA(phoneToken);
        if (StringUtils.isBlank(sign)) return null;

        String currentTimeStr = DateUtil.format(new Date(), "yyyyMMddHHmmssSSS");
        String msgId = IdUtil.fastSimpleUUID();

        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("version", "2.0");
        paramMap.put("msgid", msgId);
        paramMap.put("systemtime", currentTimeStr);
        paramMap.put("strictcheck", "0");
        paramMap.put("appid", getAppId());
        paramMap.put("token", phoneToken);
        paramMap.put("sign", sign);
        paramMap.put("encryptionalgorithm", encryptionAlgorithm_RSA);

        Map<String, String> headerMap = Maps.newHashMap();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Accept", "*/*");
        headerMap.put("Host", "onekey2.cmpassport.com");
        headerMap.put("Connection", "keep-alive");

        String responseStr = HttpUtils.postRequestWithJson(tokenUrl, headerMap, paramMap);
        System.out.println(StrFormatter.format("移动解析手机号返回结果:{}", responseStr));

        if (StringUtils.isNotBlank(responseStr)) {
            JSONObject responseJsonObject = JSONObject.parseObject(responseStr);
            String resultCode = responseJsonObject.getString("resultCode");
            if (resultCode.equals(SUCCESS_HTTP_CODE)) {
                String msisdn = responseJsonObject.getString("msisdn");
                return parsePhoneNoWithRSA(msisdn);
            }
        }
        return null;
    }

    // ----------------------------------------
    // RSA 算法相关
    // ----------------------------------------
    private String createSignWithRSA(String token) {
        String appId = getAppId();
        String dataStr = appId + token;
        byte[] data = dataStr.getBytes();

        Signature signature;
        try {
            RSAPrivateKey privateKey = getPrivateKeyByKey(getPrivateKey1());
            signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(privateKey);
            signature.update(data);
            return byte2hex(signature.sign());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private String parsePhoneNoWithRSA(String msisdn) {
        Cipher cipher = null;
        try {
            RSAPrivateKey privateKey = getPrivateKeyByKey(getPrivateKey2());
            byte[] data = hexStr2byte(msisdn);
            cipher = Cipher.getInstance(encryptionAlgorithm_RSA);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(data);
            return new String(output, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static RSAPrivateKey getPrivateKeyByKey(String privateKey) throws
            Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(encryptionAlgorithm_RSA);
        byte[] privateKeyByte = Base64.getDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
        return (RSAPrivateKey) keyFactory.generatePrivate(priKeySpec);
    }

    // ----------------------------------------
    // SM 算法相关
    // ----------------------------------------
    private String createSignWithSM(String msgId, String currentTimeStr, String token) {
        String appId = getAppId();
        String APPSecret = getAppSecret();
        String strictCheck = "0";

        return "";
    }

    private String parsePhoneWithSm() {
        return "";
    }

    private String getAppId() {
        return propertiesProxy.get("third.login.china-mobile.appid");
    }

    private String getAppSecret() {
        return propertiesProxy.get("third.login.china-mobile.app-secret");
    }

    private String getPrivateKey1() {
        return "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAjtU+wuJNWN+3q8xzr2QLfdfwAtFdCwJ6O6wCTAA5bGLKa0hb2OwvrQpO1fFrlRKLl0XYtPAgTDKSR8p4rzUVaQIDAQABAkBa5kNm63amFNpjL16ARH87u203nd5E33LC/xkHHS1uWAsM0d2nMQ7tmp5xQ85CmNNPot0LnzVXT4zlkeBvkEGxAiEA2+gTD2PrmqPaKyZwHykRhisTmnPj+zRGhSqcl28FGAsCIQCmRrtcKeHUm7oxaSBSi4iujlvaogAViWs6O6fEOMsM2wIhALoL8AQ3Tx83vN6A2J8kSbUvQJiNr7XZlkgXsv/TZ4XdAiAuLlL3RAKe5CmQc5wwkOSDZrKIRJo1YRdQ8ySjUQrEJQIgLRG3egI8hndsju4hm/JG3hfXo3huTQyuHb6I5eaOt88=";
    }

    private String getPrivateKey2() {
        return "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAr8uiHGvbUpmQ1vYhBPpg+ccOizwsVDGvvx+RcOmtUpeerdixL4jC8swvYFTnFKCnxUZbv2THrlItt2iNKpj59wIDAQABAkBQNsqxzUU2W3wLmiNW8iht0LaCMeLISCO5Qd5Ld1Tu6h2Hm/y/1O9s/bMUHbsBSC7kykDYb9mhxwjL4kjFxdwBAiEA62hepMhJHpsWnfzNWES4vs/AMJMoRQx6dqo38Atr0hcCIQC/LFRYDCXlzG8G5RkHfhtF2g0sqA2C5Ge3/D9d6KxjIQIgFysUdX9Iwvxcg3wH8bIBxLXJon45LmKGAvvJuZRGLk0CIQC79Wa75r3AEV68BbW1IyzHYdsAI/6cydqcD1tyBlivYQIhANOVhPXyBF42Ag2rFCzMxXq1ZL6FsQ1HHxyYFSnsVdF3";
    }

    /**
     * 将二进制数组转成字符串
     *
     * @param b 二进制
     * @return 字符串
     */
    public static String byte2hex(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stem = "";
        for (byte value : b) {
            stem = (Integer.toHexString(value & 0XFF));
            if (stem.length() == 1) {
                hs.append("0").append(stem);
            } else {
                hs.append(stem);
            }
        }
        return hs.toString().toUpperCase();
    }

    /**
     * 将十六进制转换成字节数据
     *
     * @param strHex 十六进制字符串
     * @return 字节数组
     */
    public static byte[] hexStr2byte(String strHex) {
        if (strHex == null) {
            return null;
        }
        int l = strHex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strHex.substring(i * 2, i * 2 + 2),
                    16);
        }
        return b;
    }

    public static void generateKey() {
        try {
            // 指定密钥长度
            int keyLength = 512;

            // 创建密钥对生成器
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(keyLength);

            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            // 获取私钥和公钥
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();

            // 将私钥和公钥转换为PKCS#8格式的Base64编码字符串
            String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
            String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());

            System.out.println("Private Key (PKCS#8): " + privateKeyStr);
            System.out.println("Public Key: " + publicKeyStr);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}
